package org.example.xsda.service;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.example.xsda.common.PageResult;
import org.example.xsda.entity.Student;
import org.example.xsda.entity.StudentScore;
import org.example.xsda.entity.SysUser;
import org.example.xsda.exception.BusinessException;
import org.example.xsda.mapper.StudentMapper;
import org.example.xsda.mapper.StudentScoreMapper;
import org.example.xsda.mapper.SysUserMapper;
import org.example.xsda.vo.StudentScoreVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 成绩服务
 */
@Slf4j
@Service
public class ScoreService {

    @Autowired
    private StudentScoreMapper studentScoreMapper;
    
    @Autowired
    private StudentMapper studentMapper;
    
    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private RedisService redisService;

    @Autowired
    private StatisticsService statisticsService;

    // 缓存key前缀
    private static final String CACHE_KEY_SCORE_BY_STUDENT = "score:student:";

    /**
     * 分页查询成绩（带学生姓名）
     */
    public PageResult<StudentScoreVO> page(Long current, Long size, Long studentId, String semester, String courseName, String studentKeyword) {
        log.info("成绩分页查询参数 - current:{}, size:{}, studentId:{}, semester:{}, courseName:{}, studentKeyword:{}", 
                current, size, studentId, semester, courseName, studentKeyword);
        
        Page<StudentScore> page = new Page<>(current, size);
        LambdaQueryWrapper<StudentScore> wrapper = new LambdaQueryWrapper<>();
        
        // 如果有学生关键字搜索，先查询符合条件的学生ID列表
        if (StringUtils.hasText(studentKeyword)) {
            LambdaQueryWrapper<Student> studentWrapper = new LambdaQueryWrapper<>();
            studentWrapper.like(Student::getStudentNo, studentKeyword);
            List<Student> students = studentMapper.selectList(studentWrapper);
            
            // 同时根据姓名搜索
            LambdaQueryWrapper<SysUser> userWrapper = new LambdaQueryWrapper<>();
            userWrapper.like(SysUser::getRealName, studentKeyword);
            userWrapper.eq(SysUser::getRoleId, 3L); // 学生角色
            List<SysUser> users = sysUserMapper.selectList(userWrapper);
            
            // 收集所有匹配的studentId
            Set<Long> studentIds = new HashSet<>();
            for (Student student : students) {
                studentIds.add(student.getId());
            }
            for (SysUser user : users) {
                LambdaQueryWrapper<Student> sw = new LambdaQueryWrapper<>();
                sw.eq(Student::getUserId, user.getId());
                Student student = studentMapper.selectOne(sw);
                if (student != null) {
                    studentIds.add(student.getId());
                }
            }
            
            if (studentIds.isEmpty()) {
                // 没有匹配的学生，返回空结果
                return new PageResult<>(0L, new ArrayList<>(), current, size);
            }
            
            wrapper.in(StudentScore::getStudentId, studentIds);
        }
        
        if (studentId != null) {
            wrapper.eq(StudentScore::getStudentId, studentId);
        }
        if (StringUtils.hasText(semester)) {
            wrapper.eq(StudentScore::getSemester, semester);
        }
        if (StringUtils.hasText(courseName)) {
            wrapper.like(StudentScore::getCourseName, courseName);
        }
        wrapper.orderByDesc(StudentScore::getCreateTime);
        
        Page<StudentScore> scorePage = studentScoreMapper.selectPage(page, wrapper);
        
        // 转换为VO并补充学生信息
        List<StudentScoreVO> voList = new ArrayList<>();
        for (StudentScore score : scorePage.getRecords()) {
            StudentScoreVO vo = new StudentScoreVO();
            BeanUtils.copyProperties(score, vo);
            
            // 查询学生信息
            Student student = studentMapper.selectById(score.getStudentId());
            if (student != null) {
                vo.setStudentNo(student.getStudentNo());
                // 查询用户信息获取姓名
                SysUser user = sysUserMapper.selectById(student.getUserId());
                if (user != null) {
                    vo.setStudentName(user.getRealName());
                }
            }
            voList.add(vo);
        }
        
        return new PageResult<>(scorePage.getTotal(), voList, scorePage.getCurrent(), scorePage.getSize());
    }

    /**
     * 获取学生所有成绩（带缓存）
     */
    @SuppressWarnings("unchecked")
    public List<StudentScore> getByStudentId(Long studentId) {
        String cacheKey = CACHE_KEY_SCORE_BY_STUDENT + studentId;
        
        // 先从缓存中获取
        Object cached = redisService.get(cacheKey);
        if (cached != null) {
            log.debug("从缓存中获取学生成绩：studentId={}", studentId);
            return (List<StudentScore>) cached;
        }
        
        // 缓存未命中，从数据库查询
        LambdaQueryWrapper<StudentScore> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StudentScore::getStudentId, studentId);
        wrapper.orderByDesc(StudentScore::getSemester);
        List<StudentScore> scores = studentScoreMapper.selectList(wrapper);
        
        // 存入缓存（15分钟，成绩数据变化不频繁）
        redisService.set(cacheKey, scores, 15, java.util.concurrent.TimeUnit.MINUTES);
        log.debug("将学生成绩存入缓存：studentId={}", studentId);
        
        return scores;
    }

    /**
     * 新增成绩
     */
    public void add(StudentScore score) {
        score.setCreateUser(StpUtil.getLoginIdAsLong());
        studentScoreMapper.insert(score);
        
        // 清除缓存
        clearScoreCache(score.getStudentId());
        
        log.info("新增成绩成功：学生ID={}, 课程={}", score.getStudentId(), score.getCourseName());
    }

    /**
     * 更新成绩
     */
    public void update(StudentScore score) {
        StudentScore existScore = studentScoreMapper.selectById(score.getId());
        if (existScore == null) {
            throw new BusinessException("成绩记录不存在");
        }

        studentScoreMapper.updateById(score);
        
        // 清除缓存
        clearScoreCache(existScore.getStudentId());
        
        log.info("更新成绩成功：ID={}", score.getId());
    }

    /**
     * 删除成绩
     */
    public void delete(Long id) {
        StudentScore score = studentScoreMapper.selectById(id);
        if (score == null) {
            throw new BusinessException("成绩记录不存在");
        }

        studentScoreMapper.deleteById(id);
        
        // 清除缓存
        clearScoreCache(score.getStudentId());
        
        log.info("删除成绩成功：ID={}", id);
    }
    
    /**
     * 清除成绩相关缓存
     */
    private void clearScoreCache(Long studentId) {
        // 清除学生成绩缓存
        redisService.delete(CACHE_KEY_SCORE_BY_STUDENT + studentId);
        
        // 清除学生档案缓存（因为档案中包含成绩统计）
        redisService.deleteByPattern("student:profile:");
        
        // 清除统计数据缓存
        if (statisticsService != null) {
            statisticsService.clearStatisticsCache();
        }
        
        log.debug("清除成绩相关缓存：studentId={}", studentId);
    }
    
    /**
     * 获取当前学生的成绩（学生端使用）
     */
    public PageResult<StudentScore> getMyScores(Long current, Long size, String semester, String courseName) {
        // 1. 获取当前登录用户ID
        Long userId = StpUtil.getLoginIdAsLong();
        
        // 2. 根据userId查找student记录
        LambdaQueryWrapper<Student> studentWrapper = new LambdaQueryWrapper<>();
        studentWrapper.eq(Student::getUserId, userId);
        Student student = studentMapper.selectOne(studentWrapper);
        
        if (student == null) {
            throw new BusinessException("未找到学生信息，请联系管理员");
        }
        
        // 3. 查询该学生的成绩
        Page<StudentScore> page = new Page<>(current, size);
        LambdaQueryWrapper<StudentScore> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StudentScore::getStudentId, student.getId());
        
        if (StringUtils.hasText(semester)) {
            wrapper.eq(StudentScore::getSemester, semester);
        }
        if (StringUtils.hasText(courseName)) {
            wrapper.like(StudentScore::getCourseName, courseName);
        }
        wrapper.orderByDesc(StudentScore::getSemester)
               .orderByDesc(StudentScore::getCreateTime);
        
        Page<StudentScore> scorePage = studentScoreMapper.selectPage(page, wrapper);
        
        log.info("学生查询成绩：studentId={}, 共{}条", student.getId(), scorePage.getTotal());
        
        return new PageResult<>(scorePage.getTotal(), scorePage.getRecords(), scorePage.getCurrent(), scorePage.getSize());
    }
    
    /**
     * 学生导出自己的成绩单
     */
    public void exportMyScores(HttpServletResponse response) {
        try {
            // 1. 获取当前登录用户ID
            Long userId = StpUtil.getLoginIdAsLong();
            
            // 2. 根据userId查找student记录
            LambdaQueryWrapper<Student> studentWrapper = new LambdaQueryWrapper<>();
            studentWrapper.eq(Student::getUserId, userId);
            Student student = studentMapper.selectOne(studentWrapper);
            
            if (student == null) {
                throw new BusinessException("未找到学生信息，请联系管理员");
            }
            
            // 3. 查询学生信息
            SysUser user = sysUserMapper.selectById(userId);
            String studentName = user != null ? user.getRealName() : "未知";
            
            // 4. 查询该学生的所有成绩
            LambdaQueryWrapper<StudentScore> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(StudentScore::getStudentId, student.getId());
            wrapper.orderByDesc(StudentScore::getSemester)
                   .orderByDesc(StudentScore::getCreateTime);
            List<StudentScore> scores = studentScoreMapper.selectList(wrapper);
            
            // 5. 转换为导出格式（使用List<List<Object>>格式）
            List<List<Object>> exportData = new ArrayList<>();
            for (StudentScore score : scores) {
                List<Object> row = new ArrayList<>();
                row.add(score.getSemester() != null ? score.getSemester() : "");
                row.add(score.getCourseName() != null ? score.getCourseName() : "");
                row.add(score.getScore() != null ? score.getScore() : "");
                row.add(score.getCredit() != null ? score.getCredit() : "");
                row.add(score.getCreateTime() != null ? 
                        score.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : "");
                exportData.add(row);
            }
            
            // 6. 统计信息
            double totalCredits = scores.stream()
                .mapToDouble(s -> s.getCredit() != null ? s.getCredit().doubleValue() : 0.0)
                .sum();
            double averageScore = scores.isEmpty() ? 0 : scores.stream()
                .mapToDouble(s -> s.getScore() != null ? s.getScore().doubleValue() : 0.0)
                .average()
                .orElse(0.0);
            
            // 添加统计行
            List<Object> summary = new ArrayList<>();
            summary.add("");  // 学期
            summary.add("统计汇总");  // 课程名称
            summary.add(String.format("平均分: %.2f", averageScore));  // 成绩
            summary.add(String.format("总学分: %.1f", totalCredits));  // 学分
            summary.add("");  // 录入时间
            exportData.add(summary);
            
            // 7. 导出Excel
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode(studentName + "_成绩单_" + 
                    LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")), "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            
            EasyExcel.write(response.getOutputStream())
                    .head(buildScoreHead())
                    .sheet(studentName + "的成绩单")
                    .doWrite(exportData);
                    
            log.info("导出学生成绩单成功：studentId={}, studentName={}, 共{}条", 
                    student.getId(), studentName, scores.size());
        } catch (Exception e) {
            log.error("导出学生成绩单失败", e);
            throw new BusinessException("导出失败：" + e.getMessage());
        }
    }
    
    /**
     * 构建成绩单表头
     */
    private List<List<String>> buildScoreHead() {
        List<List<String>> head = new ArrayList<>();
        head.add(Collections.singletonList("学期"));
        head.add(Collections.singletonList("课程名称"));
        head.add(Collections.singletonList("成绩"));
        head.add(Collections.singletonList("学分"));
        head.add(Collections.singletonList("录入时间"));
        return head;
    }
}

